package cn.wp.common.core.web.client;

import cn.wp.common.core.WpProperties;
import cn.wp.common.core.WpVar;
import cn.wp.common.core.authentication.AuthenticationProperties;
import cn.wp.common.core.authentication.util.TokenUtil;
import cn.wp.common.core.dto.WpResult;
import cn.wp.common.core.exception.WpException;
import cn.wp.common.core.exception.WpRestException;
import cn.wp.common.core.exception.WpRestServiceException;
import cn.wp.common.core.web.WpWebContext;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 服务请求客户端
 *
 * 支持service直接本地调用,rest远程调用两种方式
 *
 * Created by chenyb on 2019/10/15
 */
@Slf4j
public class ServiceTemplate {

    @Autowired
    private LoadBalanceRestTemplate loadBalanceRestTemplate;

    @Autowired
    private SimpleRestTemplate simpleRestTemplate;

    @Autowired
    private AuthenticationProperties authenticationProperties;

    @Autowired
    private WpProperties wpProperties;

    public <T> T post(ServiceRequest serviceRequest){
        return execute(serviceRequest,HttpMethod.POST);
    }

    /**
     *
     * 如果你是get带参，
     * 如果需要通过map的形式传参。
     * 你url要这样写，通过http://172.16.88.128/shortmessageservice.asmx/Send?sysName={sysName}&phoneNumbers={phoneNumbers}&content={content}&priority={priority}
     * 参数与你最后一个map的key对应
     *
     * @param serviceRequest
     * @param <T>
     * @return
     */
    public <T> T get(ServiceRequest serviceRequest){
        return execute(serviceRequest,HttpMethod.GET);
    }

    private <T> T execute(ServiceRequest serviceRequest,HttpMethod method){
        MultiValueMap<String,Object> parameterMap = serviceRequest.getParameterMap();

        String tokenId = "";
        String tokenValue = "";

        // request 为空说明未走WebContextInterceptor拦截器或不是一个web工程发起的请求
        if(WpWebContext.isEmpty()){
//            request = new MockHttpServletRequest();
//            request.setAttribute(WpVar.TOKEN_ID_KEY,WpVar.SUPER_TOKEN_ID);
//            // 赋值超级token
//            request.setAttribute(WpVar.TOKEN_VALUE_KEY,WpVar.SUPER_TOKEN_VALUE);
//            WpWebContext.init(new WpWebContext.Context(request,new MockHttpServletResponse(),null));
            tokenId = WpVar.SUPER_TOKEN_ID;
            tokenValue = WpVar.SUPER_TOKEN_VALUE;
        }else{
            HttpServletRequest request = WpWebContext.getRequest();
            tokenId = (String)request.getAttribute(WpVar.TOKEN_ID_KEY);
            tokenValue = (String)request.getAttribute(WpVar.TOKEN_VALUE_KEY);
        }

        // 必传值
        parameterMap.add(authenticationProperties.getTokenName(), TokenUtil.self().encode(tokenValue));
        parameterMap.add(WpVar.RESPONSE_BODY_TYPE,WpVar.RESPONSE_NORMAL_BODY);

        //T result = (T)restTemplate.postForObject(serviceRequest.getServiceUrl(),WpWebContext.getRequest(),serviceRequest.getReturnType(),serviceRequest.getParameterMap());
        // T result = (T)restTemplate.postForObject(serviceRequest.getServiceUrl(),WpWebContext.getRequest(),serviceRequest.getReturnType(),serviceRequest.getParameterMap());

        //HttpHeaders headers = new HttpHeaders();
        //headers.setContentType(MediaType.APPLICATION_JSON);
        //headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

       /* //person list
        List<Person> personList = new ArrayList<Person>();
        Person person = new Person();
        person.setName("UserOne");
        personList.add(person);*/

        //httpEnitity
        //HttpEntity<Object> requestEntity = new HttpEntity<>();

        //restTemplate.postForObject()

       // HttpEntity<String> entity = new HttpEntity<String>(reqJsonStr,headers);

        ResponseEntity<?> responseEntity = null;
        if(HttpMethod.POST == method){
            log.info("Service.Url = " + serviceRequest.getServiceUrl());
            HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<MultiValueMap<String,Object>>(parameterMap);
            if(serviceRequest.isLoadBalance()){
                responseEntity = loadBalanceRestTemplate.exchange(
                        serviceRequest.getServiceUrl(),
                        method,
                        httpEntity,
                        serviceRequest.getReturnType()
                );
            }else{
                responseEntity = simpleRestTemplate.exchange(
                        serviceRequest.getServiceUrl(),
                        method,
                        httpEntity,
                        serviceRequest.getReturnType()
                );
            }

        }else{
            log.info("Service.Url = " + serviceRequest.getServiceUrl() + serviceRequest.buildQueryString());
            HttpHeaders headers = new HttpHeaders();
            HttpEntity<?> httpEntity = new HttpEntity<>(headers);
            if(serviceRequest.isLoadBalance()){
                responseEntity = loadBalanceRestTemplate.exchange(
                        serviceRequest.getServiceUrl() + serviceRequest.buildQueryString(),
                        method,
                        httpEntity,
                        serviceRequest.getReturnType()
                );
            }else{
                responseEntity = simpleRestTemplate.exchange(
                        serviceRequest.getServiceUrl() + serviceRequest.buildQueryString(),
                        method,
                        httpEntity,
                        serviceRequest.getReturnType()
                );
            }
        }

        Object result = (T)responseEntity.getBody();
        if((result instanceof WpResult)){
            WpResult<T> wpResult = (WpResult)result;
            // 错误结果
            if(wpResult.isError()){
                throw new WpRestException("服务调用失败，错误信息：" + wpResult.getMessage());
            }

            // 鉴权相关失败结果
            if(wpResult.isAuthFailure()){
                throw new WpRestServiceException(wpResult);
            }

            // 其他逻辑失败


            // 仅返回数据
//            if(serviceRequest.isReturnDataOnly()){
//                return wpResult.getDataBody();
//            }
        }

        return (T)responseEntity.getBody();

    }


}
